package org.example.singleton;


/**
 * DCL Double Check Locking Singleton
 */
public class Mgr {
    //为什么加volatile?
    /**
     * new 一个对象时 会有三个重要的步骤
     *   0    new   #2   <T>   ---->  此时会new一个半初始化状态的一个对象  里面属性值默认为0
     *   1    dup   #3   <T>   ---->  此时会复制一个引用  指向这个半初始化状态的对象
     *   4    invokespecial   #4   <T>   ---->  此时会调用构造函数  初始化这个对象 把这个属性赋值
     *   7    astore_1        ----->  会让new的对象与初始化的属性建立关联
     *   8    return          ----->
     *
     *
     *   在多线程当中 会出现指令重排序
     *   此时如果 astore_1 与   invokespecial调换顺序  就会出现大问题 如果此时你的属性是一个表示100w的订单  如果发生的指令重排序  那么可能导致订单的数量为0
     *   因为此时会把一个半初始化状态的对象给别的线程使用  造成数据不一致的问题
     *   所以需要加volatile关键字  保证指令顺序的一致性
     */
    private static volatile Mgr INSTANCE;


    private Mgr() {
    }


    public static Mgr getInstance() {
        //业务代码
        if (INSTANCE == null) {
            //双重检查锁定
            synchronized (Mgr.class) {
                if (INSTANCE == null) {
                    try{
                        Thread.sleep(1);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                    INSTANCE = new Mgr();
                }
            }
        return INSTANCE;
    }
}
